﻿#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "time.h"
#include <Includes.h>
#include <Opp_ErrorCode.h>
#include <APP_Main.h>
#include <SVS_Time.h>
#include <SVS_Para.h>
#include "OPP_Debug.h"
#include "DRV_EC600S_Event.h"

static ST_TIME g_stTime={
	.Year = 2000,
	.Month= 01,
	.Day= 01,
	.Hour= 00,
	.Min= 00,
	.Sencond= 00,
	.Zone= DEFAULT_ZONE
};
static U32 g_ulTimeHookTick = 0;
static T_MUTEX g_stClkSrcMutex;
static T_MUTEX g_ulTimeSem;
TimerHandle_t xTimer;
static U32 g_sulRtcSynFlag = 0;
static U8 g_ucClkSrc = DEFAULT_CLK_BIT;
static ST_UPDATE_PERIOD g_stUpdatePeriod = {
	.updatePeriod = NBIOT_ATCLCK_NOTIME_TO
};
static ST_RECV_TIME g_stRecvTime = {
    .src = UNKNOW_TSRC,
	.recvTime = NO_RECV_TIME,
};

//内部函数声明
int RtcIsOk();
int RtcStSet(U8 st);

//判断是否为闰年:若为闰年，返回1；若非闰年，返回0
int leap_year(int year)
{
	if((year%400==0) || ((year%100!=0) && (year%4==0))) return 1;
	else return 0;
 }


U8 get_zone(){
    S8 zone;
    MUTEX_LOCK(g_ulTimeSem, MUTEX_WAIT_ALWAYS);
    zone = g_stTime.Zone;
    MUTEX_UNLOCK(g_ulTimeSem);
    return zone;
}

U8 set_zone(S8 zone){
    MUTEX_LOCK(g_ulTimeSem, MUTEX_WAIT_ALWAYS);
    g_stTime.Zone=zone;
    MUTEX_UNLOCK(g_ulTimeSem);
    return 0;
}

/***************************************************************************//**
 * \brief       Convert time struct to UTC seconds.
 * \param       year : [1900, ..., 2018, ...]
 * \param       mon  : [1, 12]
 * \param       day  : [1, 31]
 * \param       hour : [0, 23]
 * \param       min  : [0, 59]
 * \param       sec  : [0, 59]
 * \return      seconds from 1970-1-1 0:0:0
 * \author      glic
 * \note        timezone is ignored
 ******************************************************************************/
unsigned long mktime32 (unsigned int year, unsigned int mon,
    unsigned int day, unsigned int hour,
    unsigned int min, unsigned int sec)
{
    if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
         mon += 12;      /* Puts Feb last since it has leap day */
         year -= 1;
    }

    return (((
             (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
             year*365 - 719499
          )*24 + hour - get_zone()/* now have hours */
       )*60 + min /* now have minutes */
    )*60 + sec; /* finally seconds */
}

#define SECS_PER_HOUR        (60 * 60)
#define SECS_PER_DAY         (SECS_PER_HOUR * 24)
#define DIV(a, b)            ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))

#define __isleap(year) \
    ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))

/***************************************************************************//**
 * \brief       Convert UTC seconds to tm struct.
 * \param       t : seconds from 1970-1-1 0:0:0
 * \param       tp : tm struct pointer
 * \return      0 : overflow error
 * \return      1 : success
 * \author      glic __offtime
 * \note        timezone is ignored
 *               struct tm
 *               {
 *                  int tm_sec;            Seconds. [0-60] (1 leap second)
 *                  int tm_min;            Minutes. [0-59]
 *                  int tm_hour;           Hours.   [0-23]
 *                  int tm_mday;           Day.     [1-31]
 *                  int tm_mon;            Month.   [0-11]
 *                  int tm_year;           Year - 1900.
 *                  int tm_wday;           Day of week. [0-6]
 *                  int tm_yday;           Days in year.[0-365]
 *               }
 ******************************************************************************/
int gmtime32 (const unsigned long t, struct tm *tp)
{
    const unsigned short int __mon_yday[2][13] =
    {
        /* Normal years.  */
        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
        /* Leap years.  */
        { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
    };
    long int days, rem, y;
    const unsigned short int *ip;

    days = t / SECS_PER_DAY;
    rem = t % SECS_PER_DAY;
    while (rem < 0)
    {
        rem += SECS_PER_DAY;
        --days;
    }
    while (rem >= SECS_PER_DAY)
    {
        rem -= SECS_PER_DAY;
        ++days;
    }

    tp->tm_hour = rem / SECS_PER_HOUR;
    rem %= SECS_PER_HOUR;
    tp->tm_min = rem / 60;
    tp->tm_sec = rem % 60;
    /* January 1, 1970 was a Thursday.  */
    tp->tm_wday = (4 + days) % 7;
    if (tp->tm_wday < 0)
    tp->tm_wday += 7;
    y = 1970;

    while (days < 0 || days >= (__isleap (y) ? 366 : 365))
    {
        /* Guess a corrected year, assuming 365 days per year.  */
        long int yg = y + days / 365 - (days % 365 < 0);
        /* Adjust DAYS and Y to match the guessed year.  */
        days -= ((yg - y) * 365
               + LEAPS_THRU_END_OF (yg - 1)
               - LEAPS_THRU_END_OF (y - 1));
        y = yg;
    }

    tp->tm_year = y - 1900;
    if (tp->tm_year != y - 1900)
    {
        /* The year cannot be represented due to overflow.  */
        //__set_errno (EOVERFLOW);
        return 1;
    }

    tp->tm_yday = days;
    ip = __mon_yday[__isleap(y)];
    for (y = 11; days < (long int) ip[y]; --y)
        continue;
    days -= ip[y];
    tp->tm_mon = y;
    tp->tm_mday = days + 1;
    return 0;
}

/***************************************************************************//**
 * \brief       获取本地GMT时间.
 * \param       time(ms) : seconds from 1970-1-1 0:0:0
 * \param       t : GMT时间
 * \return      NONE
 * \author      glic __offtime
 ******************************************************************************/
int localtime32 (unsigned long t, struct tm *tp)
{
    int timezone = get_zone()*3600;
    t += timezone;
    return gmtime32 (t, tp);
}

/***************************************************************************//**
 * \brief       Convert UTC seconds to tm struct.
 * \param       time(ms) : seconds from 1970-1-1 0:0:0
 * \param       t : GMT时间
 * \return      NONE
 * \author      glic __offtime
 ******************************************************************************/
void my_local_time(my_time_t time,ST_TIME *t)
{
    struct tm tm_time;
    localtime32(time,&tm_time);
    t->Year = tm_time.tm_year+1900;
    t->Month = tm_time.tm_mon+1;
    t->Day = tm_time.tm_mday;
    t->Hour = tm_time.tm_hour;
    t->Min = tm_time.tm_min;
    t->Sencond = tm_time.tm_sec;
}

char check_date(short w_year,char w_month,char w_date)
{
    unsigned char Month_buf[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };

    if (w_month==2)
        (((w_year%4==0)&&(w_year%100!=0))||(w_year%400==0))?Month_buf[1]+=1:Month_buf[1];

    if (w_month>12||w_month<1||w_date>Month_buf[w_month-1]||w_date<1)
        return 1;

    return 0;
}
char check_sdate(char w_month,char w_date)
{
    unsigned char Month_buf[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };

    Month_buf[1]+=1;
    if (w_month>12||w_month<1||w_date>Month_buf[w_month-1]||w_date<1)
        return 1;

    return 0;

}

char check_time(char hour,char min, char sec)
{
	if((/*hour<0||*/hour>23)||(/*min<0||*/min>59)||(/*sec<0||*/sec>59))
		return 1;
	return 0;
}

char check_stime(char hour,char min)
{
	return check_time(hour,min,0);
}

static int days_of_month(ST_TIME * time)
{
    int days = 0;

    switch (time->Month)
    {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            days = 31;
            break;

        case 4:
        case 6:
        case 9:
        case 11:
            days = 30;
            break;

        case 2:
            if (leap_year(time->Year))
            { days = 29; }
            else
            { days = 28; }

            break;
    }

    return days;
}

void  time_zone_convert(ST_TIME *time, U8 src_tz, U8 des_tz)
{
    U8 hour, delta = 0;

    /* Check time zone */
    if (time == NULL || des_tz > 12 /*|| des_tz < -12*/)
        return;

    if (des_tz == src_tz)
        return;

    /* Ready to convert time */
    hour = (time->Hour + (des_tz - src_tz)) % 24;
    //printf("time->hour=%d hour = %d des_tz=%d src_tz=%d\r\n", time->hour, hour, des_tz, src_tz);

    if (/*(hour >= 0) &&*/( hour < time->Hour) && (des_tz > src_tz)) {
        delta = 1;
    }/* else if (hour < 0) {
        hour += 24;
        delta = -1;
    }*/

    //printf("delta = %d time->day=%d ,hour :%d \r\n", delta, time->day,hour);
    time->Hour = hour;
    time->Day = time->Day + delta;

    if (time->Day == 0 || time->Day > days_of_month(time)) {
        time->Day = 1;
        time->Month = time->Month + delta;

        if (time->Month == 0 || time->Month > 12) {
            time->Month = 1;
            time->Year = time->Year + delta;
        }
    }

}

int TimeInit(void)
{
	int ret;
	ST_CLKSRC stClkSrc;

	/*2000/1/1 0:0:0*/
	g_stTime.Year = 2000;
	g_stTime.Month= 01;
	g_stTime.Day= 01;
	g_stTime.Hour= 00;
	g_stTime.Min= 00;
	g_stTime.Sencond= 00;
	g_stTime.Zone= DEFAULT_ZONE;
	g_ulTimeHookTick = OppTickCountGet();

	MUTEX_CREATE(g_stClkSrcMutex);
	MUTEX_CREATE(g_ulTimeSem);
	MUTEX_CREATE(g_stUpdatePeriod.mutex);
	MUTEX_CREATE(g_stRecvTime.mutex);
	ret = TimeGetClkSrcFromFlash(&stClkSrc);
	if(OPP_SUCCESS == ret){
        TimeSetClockSrc(stClkSrc.clkSrc);
	}

	if(GPS_CLK_BIT&g_ucClkSrc){
        TimeFromGpsClock();
	}

	if(RTC_CLK_BIT&g_ucClkSrc){
        if(0 == RtcIsOk())
		    TimeInitRtc();
	}


	return OPP_SUCCESS;
}

/**
 *******************************************************************************
 *@brief            获取设备本地GMT时间
 *@param            time 出参，当前GMT时间
 *@return           .
 *******************************************************************************
 */
void TimeGet(ST_TIME* time)
{
	U32 elapseTick;
	my_time_t t;
	struct tm time_field;
    ST_TIME stTime;

	if(time == NULL)
		return;

	// lock
	MUTEX_LOCK(g_ulTimeSem,MUTEX_WAIT_ALWAYS);
	elapseTick = OppTickCountGet() - g_ulTimeHookTick;
    memcpy(&stTime,&g_stTime,sizeof(ST_TIME));
	MUTEX_UNLOCK(g_ulTimeSem);

	t = mktime32(stTime.Year,stTime.Month,stTime.Day,stTime.Hour,stTime.Min,stTime.Sencond);/*2017-01-01 00:00:00*/
	t  += elapseTick/1000;
	localtime32(t, &time_field);
	time_field.tm_year += 1900;
	time_field.tm_mon += 1;
	time->Year = time_field.tm_year;
	time->Month = time_field.tm_mon;
	time->Day = time_field.tm_mday;
	time->Hour = time_field.tm_hour;
	time->Min= time_field.tm_min;
	time->Sencond = time_field.tm_sec;
	time->Zone = get_zone();

	return;
}
/**
 *******************************************************************************
 *@brief            获取设备本地时间带返回值
 *@param            time 出参，当前时间
 *@return           0 有效时间，1预估时间
 *******************************************************************************
 */
U32 TimeGetRet(ST_TIME* time)
{
    ST_RECV_TIME stRecvTime;

    TimeGet(time);
    timeRecvTimeGet(&stRecvTime);
	if(NO_RECV_TIME == stRecvTime.recvTime){
		return 1;
	}
    return 0;
}

int TimeUpdatePeriodSet(U32 period)
{
	MUTEX_LOCK(g_stUpdatePeriod.mutex,MUTEX_WAIT_ALWAYS);
	g_stUpdatePeriod.updatePeriod = period;
	MUTEX_UNLOCK(g_stUpdatePeriod.mutex);
	return 0;
}

U32 TimeUpdatePeriodGet(void)
{
	U32 period;

	MUTEX_LOCK(g_stUpdatePeriod.mutex,MUTEX_WAIT_ALWAYS);
	period = g_stUpdatePeriod.updatePeriod;
	MUTEX_UNLOCK(g_stUpdatePeriod.mutex);
	return period;
}

int TimeRecvTimeSet(U8 src, U8 hasRecv)
{
	MUTEX_LOCK(g_stRecvTime.mutex,MUTEX_WAIT_ALWAYS);
    g_stRecvTime.src = src;
	if(NO_RECV_TIME == hasRecv)
		g_stRecvTime.recvTime = NO_RECV_TIME;
	else
		g_stRecvTime.recvTime = RECV_TIME;
	MUTEX_UNLOCK(g_stRecvTime.mutex);
	return 0;
}

U8 timeRecvTimeGet(ST_RECV_TIME *pstRecvTime)
{
	//U8 hasRecv;

	MUTEX_LOCK(g_stRecvTime.mutex,MUTEX_WAIT_ALWAYS);
	/*if(NO_RECV_TIME == g_stRecvTime.recvTime)
		hasRecv = NO_RECV_TIME;
	else
		hasRecv = RECV_TIME;*/
    memcpy(pstRecvTime, &g_stRecvTime, sizeof(ST_RECV_TIME));
	MUTEX_UNLOCK(g_stRecvTime.mutex);

	return 0;
}

int TimeCacWeek(int y,int m, int d)
{
    if(m==1||m==2) {
        m+=12;
        y--;
    }

    int iWeek=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;
/*
    switch(iWeek)
    {
    case 0: DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"monday\n"); break;
    case 1: DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"tuesday\n"); break;
    case 2: DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"wednesday\n"); break;
    case 3: DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"thursday\n"); break;
    case 4: DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"friday\n"); break;
    case 5: DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"saturday\n"); break;
    case 6: DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"sunday\n"); break;
    }
*/
	return iWeek;
}

int TimeLeapYear(int year)
{
	int leap;

	if ((year%4==0&&year%100!=0)||(year%400==0))
	{
		leap = 1;
	}
	else
	{
		leap = 0;
	}

	return leap;
}

int TimeSetClockSrc(U8 ucClkSrc)
{
	g_ucClkSrc = ucClkSrc;

	return 0;
}

int TimeGetClockSrc(void)
{
	return g_ucClkSrc;
}

U32 TimeGetClkSrcFromFlash(ST_CLKSRC *pstClkSrc)
{
	int ret = OPP_SUCCESS;
	unsigned int len = sizeof(ST_CLKSRC);
	ST_CLKSRC stClkSrc;

	MUTEX_LOCK(g_stClkSrcMutex,100);
	ret = AppParaRead(APS_PARA_MODULE_APS_TIME, CLKSRC_ID, (unsigned char *)&stClkSrc, &len);
	if(OPP_SUCCESS != ret){
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO, "TimeGetClkSrcFromFlash fail ret %d\r\n",ret);
		MUTEX_UNLOCK(g_stClkSrcMutex);
		return OPP_FAILURE;
	}

	memcpy(pstClkSrc,&stClkSrc,sizeof(ST_CLKSRC));
	MUTEX_UNLOCK(g_stClkSrcMutex);
	return OPP_SUCCESS;
}

U32 TimeSetClkSrcToFlash(ST_CLKSRC *pstClkSrc)
{
	int ret = OPP_SUCCESS;

	MUTEX_LOCK(g_stClkSrcMutex,MUTEX_WAIT_ALWAYS);
	ret = AppParaWrite(APS_PARA_MODULE_APS_TIME, CLKSRC_ID, (unsigned char *)pstClkSrc, sizeof(ST_CLKSRC));
	if(OPP_SUCCESS != ret){
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO, "TimeSetClkSrcToFlash fail ret %d\r\n",ret);
		MUTEX_UNLOCK(g_stClkSrcMutex);
		return OPP_FAILURE;
	}
	MUTEX_UNLOCK(g_stClkSrcMutex);
	return OPP_SUCCESS;
}

/*计算行政时区*/
int calculateTimezone(double lat,double lon){
    int a,b,c,timezone;
    a = (int)(fabs(lon)+0.5);// 对经度进行四舍五入，且取正整数
    b = a/15; // 商
    c = a%15; // 余数
    if((lat >=17.9 && lat <=53 && lon>=75 && lon<=125) || (lat>=40 && lat <=53 && lon>=125 && lon<= 135)){// 如果经纬度处于中国版图内，则都划为东8区，为什么要这样划分详见第三节
    timezone = 8;
    }
    else{

        if(c > 7.5)
            timezone = b+1;
        else
            timezone = b;
        if(lon > 0.0f)
            timezone = timezone;
        else
            timezone = (-1)*timezone;
    }
    return timezone;
}

/*
*reture: 0成功，1获取时间失败
*/
int TimeFromGpsClock(void)
{
#if 0
	int len = 0;
	char buf[50] = {0};
	gps_time_info_t info;
	long double lat;
	long double lng;
	int ret;

#if 0
#ifdef DEBUG
	strcpy(info.UTC_Date, "180420");
	strcpy(info.UTC_Time, "020101.111");
#else
	ret = GpsTimeInfoGet(&info,100);
#endif
	if(!IS_ZERO((char *)info.UTC_Date, sizeof(info.UTC_Date)) && !IS_ZERO((char *)info.UTC_Time, sizeof(info.UTC_Time)))
#endif
	ret = GpsTimeInfoGet(&info,100);
	DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"GpsTimeInfoGet ret %d\r\n", ret);

	if(0 == ret)
	{
		DEBUG_LOG(DEBUG_MODULE_LOC, DLL_INFO, "GPS time\r\n");
		//wangtao
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"TimeFromGpsClock Lock\r\n");
		MUTEX_LOCK(g_ulTimeSem,MUTEX_WAIT_ALWAYS);

		//day
		memset(buf, 0, sizeof(buf));
		strncpy(buf, info.UTC_Date, 2);
		len += 2;
		buf[2] = '\0';
		g_stTime.Day = atoi(buf);
		//month
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Date[len], 2);
		buf[2] = '\0';
		len += 2;
		g_stTime.Month = atoi(buf);
		//year
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Date[len], 2);
		buf[2] = '\0';
		len += 2;
		g_stTime.Year = atoi(buf);
		g_stTime.Year += 2000;
		//hh
		len = 0;
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Time[len], 2);
		buf[2] = '\0';
		len += 2;
		g_stTime.Hour = atoi(buf);
		//mm
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Time[len], 2);
		buf[2] = '\0';
		len += 2;
		g_stTime.Min= atoi(buf);
		//ss.sss->ss
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Time[len], 2);
		buf[2] = '\0';
		len += 2;
		g_stTime.Sencond = atoi(buf);
		//zone
		//OppLocationGet(GPS_LOC);
		LocGetLat(&lat);
		LocGetLng(&lng);
		g_stTime.Zone = calculateTimezone(lat,lng);
		time_zone_convert(&g_stTime,0,g_stTime.Zone);
		g_ulTimeHookTick = OppTickCountGet();
		//wangtao
		MUTEX_UNLOCK(g_ulTimeSem);
		TimeRecvTimeSet(GPS_TSRC,RECV_TIME);
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"y %d, m %d, d %d, h %d, m %d, s %d, z %d\r\n", g_stTime.Year, g_stTime.Month, g_stTime.Day,g_stTime.Hour, g_stTime.Min, g_stTime.Sencond, g_stTime.Zone);
		return OPP_SUCCESS;
	}
#endif
	return OPP_FAILURE;
}


/**
 *******************************************************************************
 *@brief            从GPS获取时间
 *@param            time 出参时间
 *@return           0成功，1获取时间失败
 *******************************************************************************
 */
int TimeGetFromGpsClock(ST_TIME *time)
{
#if 0
	int len = 0;
	char buf[50] = {0};
	gps_time_info_t info;
	long double lat;
	long double lng;
	int ret;

#if 0
#ifdef DEBUG
	strcpy(info.UTC_Date, "180420");
	strcpy(info.UTC_Time, "020101.111");
#else
	ret = GpsTimeInfoGet(&info,100);
#endif
	if(!IS_ZERO((char *)info.UTC_Date, sizeof(info.UTC_Date)) && !IS_ZERO((char *)info.UTC_Time, sizeof(info.UTC_Time)))
#endif
	ret = GpsTimeInfoGet(&info,100);
	DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"GpsTimeInfoGet ret %d\r\n", ret);

	if(0 == ret)
	{
		DEBUG_LOG(DEBUG_MODULE_LOC, DLL_INFO, "GPS time\r\n");
		//wangtao
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"TimeGetFromGpsClock Lock\r\n");
		//day
		memset(buf, 0, sizeof(buf));
		strncpy(buf, info.UTC_Date, 2);
		len += 2;
		buf[2] = '\0';
		time->Day = atoi(buf);
		//month
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Date[len], 2);
		buf[2] = '\0';
		len += 2;
		time->Month = atoi(buf);
		//year
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Date[len], 2);
		buf[2] = '\0';
		len += 2;
		time->Year = atoi(buf);
		time->Year += 2000;
		//hh
		len = 0;
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Time[len], 2);
		buf[2] = '\0';
		len += 2;
		time->Hour = atoi(buf);
		//mm
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Time[len], 2);
		buf[2] = '\0';
		len += 2;
		time->Min= atoi(buf);
		//ss.sss->ss
		memset(buf, 0, sizeof(buf));
		strncpy(buf, &info.UTC_Time[len], 2);
		buf[2] = '\0';
		len += 2;
		time->Sencond = atoi(buf);
		//zone
		//OppLocationGet(GPS_LOC);
		LocGetLat(&lat);
		LocGetLng(&lng);
		time->Zone = calculateTimezone(lat,lng);
		time_zone_convert(time,0,time->Zone);
		//wangtao
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"y %d, m %d, d %d, h %d, m %d, s %d, z %d\r\n",
		time->Year, time->Month, time->Day,time->Hour, time->Min, time->Sencond, time->Zone);
		return OPP_SUCCESS;
	}
#endif
	return OPP_FAILURE;
}

/*FOR NBIOT*/
int TimeSetCallback(U8 year, U8 month, U8 day, U8 hour, U8 min, U8 second, S8 zone)
{
	MUTEX_LOCK(g_ulTimeSem, MUTEX_WAIT_ALWAYS);

	g_stTime.Year = year + 2000;
	g_stTime.Month = month;
	g_stTime.Day = day;
	g_stTime.Hour = hour;   //格林尼治时间
	g_stTime.Min = min;
	g_stTime.Sencond = second;
	g_stTime.Zone = zone/4;

	time_zone_convert(&g_stTime,0,g_stTime.Zone);
	g_ulTimeHookTick = OppTickCountGet();

	MUTEX_UNLOCK(g_ulTimeSem);

	return OPP_SUCCESS;
}

/*手动直接设置当前时间*/
int TimeSet(U8 year, U8 month, U8 day, U8 hour, U8 min, U8 second, S8 zone)
{
	MUTEX_LOCK(g_ulTimeSem, MUTEX_WAIT_ALWAYS);

	if(month > 12 || day > 31 || hour > 23 || min > 60 || second > 60 || zone > 12 || zone < -12){
		MUTEX_UNLOCK(g_ulTimeSem);
		return OPP_FAILURE;
	}

	g_stTime.Year = year + 2000;
	g_stTime.Month = month;
	g_stTime.Day = day;
	g_stTime.Hour = hour;
	g_stTime.Min = min;
	g_stTime.Sencond = second;
	g_stTime.Zone = zone;
	g_ulTimeHookTick = OppTickCountGet();
	MUTEX_UNLOCK(g_ulTimeSem);

	return OPP_SUCCESS;
}

/**
 *******************************************************************************
 *@brief            从NBIOT更新设备时间
 *@return           .
 *******************************************************************************
 */
int TimeFromNbiotClockEvent(void)
{
	//char buf[36] = {0};
	int ret = OPP_SUCCESS;
    ST_TIME time;

    //CAT1没驻网不允许获取时间,此时时间格式不对
    //+CCLK: "70/01/01,00:13:55+00"
	if(!NeulDevIsReady()){
		return OPP_SUCCESS;
	}

    ret=EC600S_CCLK_EVENT_DO(&time, EVENT_WAIT_DEFAULT);
    if(0!=ret)
        return ret;

    TimeSetCallback(time.Year,time.Month,time.Day,time.Hour,time.Min,time.Sencond,get_zone()*4);
    TimeUpdatePeriodSet(NBIOT_ATCLCK_TO);
    TimeRecvTimeSet(NBIOT_TSRC,RECV_TIME);

	return ret;
}

/**
 *******************************************************************************
 *@brief            从NBIOT获取时间
 *@param            time 出参，时间
 *@return           0: 成功，非0: 失败
 *******************************************************************************
 */
int TimeGetFromNbiotClockEvent(ST_TIME *time)
{
    int ret;

    ret=EC600S_CCLK_EVENT_DO(time, EVENT_WAIT_DEFAULT);
    if(0!=ret)
        return ret;
    time->Year+=2000;
    //time->Zone/=4;
    time_zone_convert(time,0,get_zone());

	return ret;
}

int TimeFromNbiotClock(void)
{
    ST_TIME t;
    int ret;

    ret=Ec600sAT_CCLK((char *)&t);
    if(ret==0)
    {
		TimeSetCallback(t.Year,t.Month,t.Day,t.Hour,t.Min,t.Sencond,get_zone()*4);
		TimeUpdatePeriodSet(NBIOT_ATCLCK_TO);
		TimeRecvTimeSet(NBIOT_TSRC,RECV_TIME);
    }
	return ret;
}

/**
 *******************************************************************************
 *@brief            根据指定源获取时间
 *@param            ucClkSrc 时间源 0:ALL_CLK     1:GPS_CLK  2:NBIOT_CLK  3:LOC_CLK  4:RTC_CLK
 *@param            zone 时区
 *@param            pstTimePara 时间
 *@return           .
 *******************************************************************************
 */
U32 TimeRead(unsigned char ucClkSrc, int*zone, ST_OPPLE_TIME * pstTimePara)
{
	U32 ret = OPP_SUCCESS;
    ST_TIME time;
    U8 ucIsExact;

	if(ALL_CLK == ucClkSrc)
	{
        if(g_ucClkSrc&RTC_CLK_BIT){
            ret = TimeGetRtcTime(&time,&ucIsExact);
        }else{
            ret = OPP_FAILURE;
        }
        if(OPP_SUCCESS != ret)
        {
            if(g_ucClkSrc&GPS_CLK_BIT){
    		    ret = TimeGetFromGpsClock(&time);
            }else{
                ret = OPP_FAILURE;
            }
    		if(OPP_SUCCESS != ret)
    		{
                if(g_ucClkSrc&NBIOT_CLK_BIT){
    			    ret = TimeGetFromNbiotClockEvent(&time);
                }else{
                    ret = OPP_FAILURE;
                }
    			if(OPP_SUCCESS != ret){
                    TimeGet(&time);
                    ret = OPP_SUCCESS;
                 }
    		}
        }
	}
	else if(GPS_CLK == ucClkSrc && g_ucClkSrc&GPS_CLK_BIT)
	{
		ret = TimeGetFromGpsClock(&time);
	}
	else if(NBIOT_CLK == ucClkSrc && g_ucClkSrc&NBIOT_CLK_BIT)
	{
		ret = TimeGetFromNbiotClockEvent(&time);
	}
	else if(LOC_CLK == ucClkSrc)
	{
		TimeGet(&time);
	}
	else if(RTC_CLK == ucClkSrc && g_ucClkSrc&RTC_CLK_BIT)
	{
        ret = TimeGetRtcTime(&time,&ucIsExact);
    }
	else
	{
		//DEBUG_LOG(DEBUG_MODULE_TIME, DLL_DEBUG, "y %d, m %d, d %d, h %d, m %d, s %d, z %d\r\n", g_stTime.Year, g_stTime.Month, g_stTime.Day,g_stTime.Hour, g_stTime.Min, g_stTime.Sencond, g_stTime.Zone);
		//printf("y %d, m %d, d %d, h %d, m %d, s %d, z %d\r\n", g_stTime.Year, g_stTime.Month, g_stTime.Day,g_stTime.Hour, g_stTime.Min, g_stTime.Sencond, g_stTime.Zone);
		return OPP_FAILURE;
	}

	pstTimePara->uwYear = time.Year;
	pstTimePara->ucMon = time.Month;
	pstTimePara->ucDay = time.Day;
	pstTimePara->ucHour = time.Hour;
	pstTimePara->ucMin = time.Min;
	pstTimePara->ucSec = time.Sencond;
	pstTimePara->usMs = 0;
	pstTimePara->ucWDay = TimeCacWeek(time.Year, time.Month, time.Day)+1;
	return ret;
}
void TimerCallback(TimerHandle_t timer)
{
	int leap = 0;
	int day = 0;

	//printf("per second plus one\r\n");
	MUTEX_LOCK(g_ulTimeSem, MUTEX_WAIT_ALWAYS);
	g_stTime.Sencond++;
	if(g_stTime.Sencond == 60)
	{
		g_stTime.Min++;
		g_stTime.Sencond = 0;
	}

	if(g_stTime.Min == 60)
	{
		g_stTime.Hour++;
		g_stTime.Min = 0;
	}

	if(g_stTime.Hour == 24)
	{
		g_stTime.Day++;
		g_stTime.Hour = 0;
	}
	if(g_stTime.Month == 1 && g_stTime.Month == 3 && g_stTime.Month == 5 && g_stTime.Month == 7 && g_stTime.Month == 8 && g_stTime.Month == 10 && g_stTime.Month == 12)
	{
		if(g_stTime.Day > 31)
		{
			g_stTime.Month++;
			g_stTime.Day = 1;
		}
	}
	else if(g_stTime.Month == 4 && g_stTime.Month == 6 && g_stTime.Month == 5 && g_stTime.Month == 9 && g_stTime.Month == 8 && g_stTime.Month == 11)
	{
		if(g_stTime.Day > 30)
		{
			g_stTime.Month++;
			g_stTime.Day = 1;
		}

	}
	else if(g_stTime.Month == 2)
	{
		leap = TimeLeapYear((g_stTime.Year));
		if(leap == 1)
		{
			day = 29;
		}
		else
		{
			day = 28;
		}
		if(g_stTime.Day > day)
		{
			g_stTime.Month++;
			g_stTime.Day = 1;
		}
	}

	if(g_stTime.Month > 12)
	{
		g_stTime.Year++;
		g_stTime.Month = 1;
	}

	//DEBUG_LOG(DEBUG_MODULE_TIME, DLL_DEBUG, "y %d, m %d, d %d, h %d, m %d, s %d, z %d\r\n", g_stTime.Year, g_stTime.Month, g_stTime.Day,g_stTime.Hour, g_stTime.Min, g_stTime.Sencond, g_stTime.Zone);
	//DEBUG_LOG(DEBUG_MODULE_TIME, DLL_DEBUG, "aaaaaaaaa");
  MUTEX_UNLOCK(g_ulTimeSem);

	//DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"y %d, m %d, d %d, h %d, m %d, s %d, z %d\r\n", g_stTime.Year, g_stTime.Month, g_stTime.Day,g_stTime.Hour, g_stTime.Min, g_stTime.Sencond, g_stTime.Zone);

	//tick_start2 = OppTickCountGet();
}

#define HAVE_RTC    0

/**
 *******************************************************************************
 *@brief            rtc初始化
 *@return           .
 *******************************************************************************
 */
U32 TimeInitRtc(void)
{
#if HAVE_RTC==1
#if defined(RX8025T)
    U32 ret;
    ret = Rtc_Init();
    if(0 == ret || 3 == ret){
        printf("get rtc time\r\n");
        TimeUpdateFromRtc();
        //TimeRecvTimeSet(RTC_TSRC,RECV_TIME);
    }else if(1 == ret){
        ST_TIME time;
        TimeGet(&time);
        TimeSetRtcTime(&time, 0);
    }
#elif defined(BM8563)
    U32 ret;
    ST_TIME stTime;
    U8 u8ResetFlag;
    ret = DevBm8563TimeGet(&stTime, &u8ResetFlag);
    if(0 == ret){
        if(DevBm8536IsTimeValid(&stTime) == 0) /* 如果时间是非法值则重新写入初始值 */
        {
            ST_TIME time;
            TimeGet(&time);
            DevBm8563TimeSet(&time, 1); /* 复位标志为1标识非准确时间 */
        }
        else
        {
            TimeUpdateFromRtc();
        }
    }
#endif

#else
    return 0;
#endif
}

/**
 *******************************************************************************
 *@brief            设置rtc时间
 *@param            time 时间参数，ucIsExactTime:0预估时间，1准确时间
 *@return           .
 *******************************************************************************
 */
U32 TimeSetRtcTime(ST_TIME *time,U8 ucIsExactTime)
{
#if HAVE_RTC==1
#if defined(RX8025T)
    U32 ret;
    ret = RTC_SET_TIME(time,ucIsExactTime);
    if(0 != ret){
        DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR,"RTC_SET_TIME err ret %d\r\n", ret);
        return ret;
    }
#elif defined(BM8563)
    U32 ret;
    U8 u8ResetFlag;
    if(ucIsExactTime==0){u8ResetFlag=1;}else{u8ResetFlag=0;}
    ret = DevBm8563TimeSet(time,u8ResetFlag);
    if(0 != ret){
        DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR,"DevBm8563TimeSet err ret %d\r\n", ret);
        return ret;
    }
#endif
#else
    return 0;
#endif
}
/**
 *******************************************************************************
 *@brief            获取rtc时间
 *@param            time 时间参数，pucIsExactTime:0客观时间，1预估时间
 *@return           0成功，非0失败
 *******************************************************************************
 */
U32 TimeGetRtcTime(ST_TIME *time, U8 *pucIsExactTime)
{
#if HAVE_RTC==1
#if defined(RX8025T)
    U32 ret;
    ret = RTC_GET_TIME(time);
    if(0 != ret && 2 != ret){
        DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR,"RTC_GET_TIME err ret %d\r\n", ret);
        return ret;
    }
    if(ret==0)
        *pucIsExactTime = 0;
    else
        *pucIsExactTime = 1;
#elif defined(BM8563)
    U32 ret;
    U8 u8ResetFlag;
    ret = DevBm8563TimeGet(time, &u8ResetFlag);
    if(0 != ret){
        DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR,"DevBm8563TimeGet err ret %d\r\n", ret);
        return ret;
    }
    //没复位客观时间，复位了预估时间
    if(u8ResetFlag==0)
        *pucIsExactTime = 0;
    else
        *pucIsExactTime = 1;
#endif
#else
    return 0;
#endif
}

U32 TimeUpdateFromRtc()
{
#if HAVE_RTC==1
    U32 ret;
    ST_TIME stTime;

#if defined(RX8025T)
    ret = RTC_GET_TIME(&stTime);
    if(0 != ret && 2 != ret){
        DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR,"RTC_GET_TIME err ret %d\r\n", ret);
        return ret;
    }
#elif defined(BM8563)
    U8 u8ResetFlag;
    ret = DevBm8563TimeGet(&stTime, &u8ResetFlag);
    if(0 != ret){
        DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR,"DevBm8563TimeGet err ret %d\r\n", ret);
        return ret;
    }
    //发生过复位后RTC时间为预估时间
    if(u8ResetFlag==1)
        ret = 2;
#endif
    U32 rtcsec,syssec;
    ST_TIME stSys;
    U32 delta;

    /*RTC_BM8563运行时间不准,增加RTC与系统时间误差判断,大于误差认为RTC故障
    2020-11-05
    wangtao
    */
    rtcsec = mktime32(stTime.Year,stTime.Month,stTime.Day,stTime.Hour,stTime.Min,stTime.Sencond);
    TimeGet(&stSys);
    syssec = mktime32(stSys.Year,stSys.Month,stSys.Day,stSys.Hour,stSys.Min,stSys.Sencond);
    if(rtcsec>=syssec)
        delta=rtcsec-syssec;
    if(rtcsec<syssec)
        delta=syssec-rtcsec;
    //系统时间与RTC时间偏差大于10分钟，设置RTC故障，不更新系统时间
    if(NeulDevIsReady()){
        if(delta>600)
        {
            RtcStSet(1);
            return 10;
        }
        else
        {
            RtcStSet(0);
        }
     }

    printf("IIC Time[%s]: %04u-%02u-%02u %02u:%02u:%02u\r\n",
        ret==0?"exact":"predict",
        stTime.Year, stTime.Month, stTime.Day,
        stTime.Hour, stTime.Min, stTime.Sencond);

    MUTEX_LOCK(g_ulTimeSem, MUTEX_WAIT_ALWAYS);
	g_stTime.Year = stTime.Year;
	g_stTime.Month = stTime.Month;
	g_stTime.Day = stTime.Day;
	g_stTime.Hour = stTime.Hour;
	g_stTime.Min = stTime.Min;
	g_stTime.Sencond = stTime.Sencond;
    g_ulTimeHookTick = OppTickCountGet();
	MUTEX_UNLOCK(g_ulTimeSem);
    if(0 == ret)
        TimeRecvTimeSet(RTC_TSRC, RECV_TIME);

#else
    return 0;
#endif
}

/**
 *******************************************************************************
 *@brief            通过flash存储标志位返回是否ok
 *@param
 *@return           0:正常，1:故障
 *******************************************************************************
 */
int RtcIsOk()
{
#if 0
    U32 ret;
    U8 st;

    //flash读不出来或没数据认为rtc ok
	ret = AppParaReadU8(APS_PARA_MODULE_APS_TIME, RTC_FAULT_ID, &st);
	if(OPP_SUCCESS != ret){
		st = 0;
	}
    return st;
#endif
    return 0;
}

/**
 *******************************************************************************
 *@brief            通过flash存储标志位返回是否ok
 *@param            st:0正常，1故障
 *@return           0:正常，非0:错误
 *******************************************************************************
 */
int RtcStSet(U8 st)
{
    U32 ret;

	ret = AppParaWriteU8(APS_PARA_MODULE_APS_TIME, RTC_FAULT_ID, st);
	if(OPP_SUCCESS != ret){
		return OPP_FAILURE;
	}
    return 0;

}
/**
 *******************************************************************************
 *@brief            设置RTC测试时间到flash
 *@param            time 时间参数
 *@return           0:成功，非0成功
 *******************************************************************************
 */
U32 TimeSetRttToFlash(ST_TIME *time)
{
    U32 ret;
    unsigned int len = sizeof(ST_TIME);

	ret = AppParaWrite(APS_PARA_MODULE_APS_TIME, RRT_ID, (unsigned char *)time, len);
	if(OPP_SUCCESS != ret){
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR, "TimeSetRttToFlash fail ret %d\r\n",ret);
		return OPP_FAILURE;
	}
    return 0;
}

/**
 *******************************************************************************
 *@brief            从flash获取rtc测试时间
 *@param            time 时间参数
 *@return           0:成功，非0成功
 *******************************************************************************
 */
U32 TimeGetRttFromFlash(ST_TIME *time)
{
    U32 ret;
    unsigned int len = sizeof(ST_TIME);

	ret = AppParaRead(APS_PARA_MODULE_APS_TIME, RRT_ID, (unsigned char *)time, &len);
	if(OPP_SUCCESS != ret){
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR, "TimeGetRttFromFlash fail ret %d\r\n",ret);
		return OPP_FAILURE;
	}
    return 0;
}

/**
 *******************************************************************************
 *@brief            rtc同步标记到flash
 *@param            同步标记
 *@return           0:成功，非0成功
 *******************************************************************************
 */
U32 TimeSetRsynToFlash(U32 ulRsyn)
{
    U32 ret;

	ret = AppParaWriteU32(APS_PARA_MODULE_APS_TIME, RSYN_ID, ulRsyn);
	if(OPP_SUCCESS != ret){
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_ERROR, "AppParaWriteU32 fail ret %d\r\n",ret);
		return OPP_FAILURE;
	}
    return OPP_SUCCESS;
}

U32 TimeGetRsyn()
{
    return g_sulRtcSynFlag;
}

void TimeLoop(void)
{
	static U32 tick_start1 = 0, tick_start2 = 0, tick_start3 = 0, tick_start4 = 0;
	static U8 init = 0;
	int ret = OPP_SUCCESS;
    static U8 first = 1;
    ST_RECV_TIME stRecvTime;
    ST_TIME time;
    static U8 doNbTime=1;


    /*nbiot入网后立即获取时间*/
    if(NBIOT_CLK_BIT&g_ucClkSrc){
    	if(NeulDevIsReady()){
            if(tick_start4 == 0 && doNbTime)
                tick_start4 = OppTickCountGet();
            /* 延迟10s获取nbiot时间 */
            if(tick_start4 > 0 && OppTickCountGet()-tick_start4 > 10000){
                DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO, "attach nbiot timeout to get nbiot time\r\n");
                ret = TimeFromNbiotClockEvent();
                if(OPP_SUCCESS != ret)
                    TimeFromNbiotClockEvent();
                doNbTime = 0;
                tick_start4 = 0;
            }
    	}
    }

	if(RTC_CLK_BIT&g_ucClkSrc){
	    timeRecvTimeGet(&stRecvTime);
	    /* 通过NBIOT获取时间成功 */
		if(NBIOT_TSRC == stRecvTime.src && RECV_TIME == stRecvTime.recvTime){
	        /*first，启动延迟写入RTC机制。关闭周期同步RTC定时器*/
	        if(first){
	            tick_start3 = OppTickCountGet();
	            /* 关闭周期同步RTC定时器 */
	            tick_start2 = 0;
	            first = 0;
	        }else{
				/*延迟写入RTC时间结束或者关闭写入RTC时间,重新开始周期同步RTC时间*/
				if(tick_start3 == 0 || TimeGetRsyn() == RSYN_FLAG){
	                if(0 == tick_start2)
	                   tick_start2 = OppTickCountGet();
	            }
	        }
		}else{
	        if(0 == tick_start2)
	           tick_start2 = OppTickCountGet();
	    }

	    /*收到NBIOT时间，等待2分钟写入RTC时间*/
	    if(tick_start3 > 0){
	    	if ((OppTickCountGet() - tick_start3) >= WAIT_WRITE_RTC_TO
                && TimeGetRsyn()!=RSYN_FLAG){
	            DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"FCT write rtc timeout\r\n");
	            TimeGet(&time);
	            TimeSetRtcTime(&time,1);
	            tick_start2 = OppTickCountGet();
	            tick_start3 = 0;
	        }
	    }
#if 0        
	    /*周期同步RTC时间*/
	    if(tick_start2 > 0){
	    	if ((OppTickCountGet() - tick_start2) >= SYNC_RTC_TO){
	            DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"~~~~~get time from rtc~~~~~~~~~\r\n");
                if(TimeUpdateFromRtc()!=0)
                {
                    //为避免系统时间偏差太大RTC故障设备运行大于7天后自动重启
                    U32 rtime;
                    //单位分钟
                    OppLampCtrlGetRtime(0,&rtime);
                    if(rtime>10080)
                    {
                        sysModeDecreaseSet();
                        ApsCoapWriteExepInfo(RTC_RST);
                        ApsCoapDoReboot();
                        OS_REBOOT();
                    }
                }
	            //g_ulTimeHookTick = OppTickCountGet();
	            //TimeRecvTimeSet(RTC_TSRC, RECV_TIME);
	            tick_start2 = 0;
	        }
	    }
#endif
	}

	if(!init)
	{
		init = 1;
		tick_start1 = OppTickCountGet();
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"~~~~~tick_start1 %lld init %d~~~~~~~~~\r\n", tick_start1, init);
	}
    /* 周期同步GPS和NBIOT时间 */
	if ((OppTickCountGet() - tick_start1) >= TimeUpdatePeriodGet()) //two hour
	{
		DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"~~~~~Opple_Nbiot_Time_Task~~~~~~~~~\r\n");
		if(GPS_CLK_BIT& g_ucClkSrc)
		{
			ret = TimeFromGpsClock();
            DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"~~~~~get time from gps~~~~~~~~~\r\n");
		}
		if(NBIOT_CLK_BIT&g_ucClkSrc)
		{
			if(GPS_CLK_BIT& g_ucClkSrc){
				/*GPS获取时间失败，从NBIOT获取时间*/
				if(OPP_SUCCESS != ret){
					ret = TimeFromNbiotClockEvent();
                    DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"~~~~~get time from nbiot for gps err~~~~~~~~~\r\n");
                }
			}
			else{
                DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"~~~~~get time from nbiot~~~~~~~~~\r\n");
				ret = TimeFromNbiotClockEvent();
			}
		}
		/* 设置RTC时间 */
		if((GPS_CLK_BIT&g_ucClkSrc)||(NBIOT_CLK_BIT&g_ucClkSrc)){
			if(OPP_SUCCESS == ret){
				if(RTC_CLK_BIT&g_ucClkSrc && TimeGetRsyn()!=RSYN_FLAG){
                    DEBUG_LOG(DEBUG_MODULE_TIME, DLL_INFO,"~~~~~syn time to rtc~~~~~~~~~\r\n");
					TimeGet(&time);
					TimeSetRtcTime(&time,1);
				}
			}
		}
		tick_start1 = OppTickCountGet();
	}

}

/**
  @brief 获取当前日期、时间 (2020-10-19 Liqi)
  @param dt 日期时间
  @retval 0:成功获取到，其他：无有效时间
  @note 该代码合并到含RTC功能的工程时需要注意实现方式
*/
int DateTimeGet(ST_TIME *dt)
{
    ST_RECV_TIME stRecvTime;

    TimeGet(dt);
    timeRecvTimeGet(&stRecvTime);
	if(NO_RECV_TIME == stRecvTime.recvTime){
	    return 1;
	}else{
	    return 0;
	}
}

/**
  @brief 日期时间对比 (2020-10-19 Liqi)
  @param dt_dst 目标日期时间
  @param dt_src 需要对比的日期时间
  @retval
    -1: dt_src早于dt_dst
    0 : 一样
    1 ：dt_src晚于dt_dst
*/
int DateTimeCmp(ST_TIME *dt_dst,ST_TIME *dt_src)
{
    my_time_t sec_dst,sec_src;

    sec_dst = mktime32(dt_dst->Year,dt_dst->Month,dt_dst->Day,dt_dst->Hour,dt_dst->Min,dt_dst->Sencond);
    sec_src = mktime32(dt_src->Year,dt_src->Month,dt_src->Day,dt_src->Hour,dt_src->Min,dt_src->Sencond);

    if(sec_src < sec_dst){
        return -1;
    }else if(sec_src > sec_dst){
        return 1;
    }else{
        return 0;
    }
}

/**
  @brief 判断当前日期时间是否超过指定日期时间
  @note 若系统没有有效时间则返回未到达
  @param dt日期时间
  @retval -1：系统无有效日期时间，0：未超过，1：超过
*/
int isNowOutOfDateTime(ST_TIME *dt)
{
    ST_TIME now;

    if(DateTimeGet(&now)!= 0){
        return -1; // 未获取到有效日期时间
    }

    if(DateTimeCmp(dt,&now) > 0){
        return 1;  // now晚于dt
    }else{
        return 0;  // now早于或等于dt
    }
}


/**
  @brief 查询保存tick值
  @param
  @retval tick值
*/
U32 HookTickGet()
{
    U32 tick;

	MUTEX_LOCK(g_ulTimeSem,MUTEX_WAIT_ALWAYS);
    tick=g_ulTimeHookTick;
	MUTEX_UNLOCK(g_ulTimeSem);
    return tick;
}

/**
  @brief 设置保存tick值
  @param tick tick值
  @retval
*/
U32 HookTickSet(U32 tick)
{
	MUTEX_LOCK(g_ulTimeSem,MUTEX_WAIT_ALWAYS);
    g_ulTimeHookTick=tick;
	MUTEX_UNLOCK(g_ulTimeSem);
    return 0;
}


